package com.chenwc.netty.tcp.handler;

import com.chenwc.netty.tcp.coder.MessageDecodeHandler;
import com.chenwc.netty.tcp.coder.MessageEncodeHandler;
import com.chenwc.netty.tcp.config.NettyProperties;
import com.chenwc.netty.tcp.listener.ServerListenerHandler;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import java.nio.charset.StandardCharsets;


/**
 * worker处理器，初始化通道以及配置对应管道的处理器 自定义了##@##分割符，通过DelimiterBasedFrameDecoder来处理拆包沾包问题；
 * 通过MessageDecodeHandler将接收消息解码处理成对象实例；
 * 通过MessageEncodeHandler将发送消息增加分割符后并编码；
 * 最后通过ServerListenerHandler根据消息类型对应处理不同消息。
 * @author chenwc
 * @date 2023/5/28 0:56
 */
public class NettyServerHandler extends ChannelInitializer<SocketChannel> {

    /**
     * 被final修饰的成员变量，一定要被赋值且只能被赋值一次，且必须是在这个成员变量所在的类对象创建之前被赋值。
     */
    private final NettyProperties nettyProperties;

    public NettyServerHandler(NettyProperties nettyProperties) {
        this.nettyProperties = nettyProperties;
    }

    @Override
    protected void initChannel(SocketChannel socketChannel) {
        // 数据分割符
        String delimiterStr = nettyProperties.getDelimiterStr();
        ByteBuf delimiter = Unpooled.copiedBuffer(delimiterStr.getBytes(StandardCharsets.UTF_8));
        ChannelPipeline pipeline = socketChannel.pipeline();
        // 使用自定义处理拆包/沾包，并且每次查找的最大长度为MaxFrameLength字节
        pipeline.addLast(new DelimiterBasedFrameDecoder(nettyProperties.getMaxFrameLength(), delimiter));
        // 将上一步解码后的数据转码为Message实例
        pipeline.addLast(new MessageDecodeHandler());
        // 对发送客户端的数据进行编码，并添加数据分隔符
        pipeline.addLast(new MessageEncodeHandler(delimiterStr));
        // 对数据进行最终处理
        pipeline.addLast(new ServerListenerHandler());
    }
}
